/**
 * FileUtilities.java
 * @author: liuex
 * 2007-12-30 ����04:10:42
 *
 * note: 
 */
package lex.mtd.core;

import java.io.*;
import java.util.logging.Logger;

import org.lex.io.IO;
import org.lex.utils.Checksums;
import org.lex.utils.Pair;

import lex.mtd.core.utils.FileUtils;
import lex.mtd.utils.Logs;

public class FileBlockSetMergeUtils {
	private static Logger log = Logs.get(FileBlockSetMergeUtils.class.getName());
	private static final boolean DELETE_FILE = true;

	public static void mergeFiles( FileBlockSet fileSet ) throws IOException
	{
		if( 0 == fileSet.getFileCount() )
			return;
		if( false == fileSet.isFinished() )
		{
			log.fine( "task not finished, won't merge" );
			return;
		}
		/*
		 * ����ʹ�õ��ǱȽϼ򵥵Ĳ��ԣ�ʵ����Ӧ����ÿ�η����������������ļ��Ѿ���ɴ���
		 * ��ʱ�򣬾�Ӧ�úϲ����ǣ�������Խ�������ع���е�IO������ɢ������������ļ���
		 * ������һЩ�������رȽϴ���ļ�ʱ����������л���ƽ��һЩ
		 */
		// now we knows that all the parts have finished
		// we merge them to a single file
		File file = new File( fileSet.getDirectory(), fileSet.getBasename() + "."
				+ fileSet.getExtname() );
		Pair<Boolean, IOException> p = FileUtils.createNewFile( file );
		if( false == p.first() )
			throw p.second();
		// ============================================================
		log.fine( fileSet.toString() );
		log.fine( "merage " + fileSet.getFileCount() + " files to: " + file.getName() );
		BufferedOutputStream out = new BufferedOutputStream( new FileOutputStream( file ),
			512 * 1024 );
		BufferedInputStream in = null;
		byte[] buf = new byte[512 * 1024];
		int len = 0;
		for( int i = 0; i < fileSet.getFileCount(); i++ )
		{
			FileBlock part = fileSet.getFileBlock( i );
			{
				long expected = part.getLength();
				long actual = part.getFile().length();
				log.fine( part.getFileName() + ": expect=" + expected + ", actual=" + actual );
			}
			in = new BufferedInputStream( new FileInputStream( part.getFile() ) );
			while( (len = in.read( buf )) != -1 )
				out.write( buf, 0, len );
			IO.closeQuietly( in );
			if( DELETE_FILE )
				FileUtils.deleteFile( part.getFile() );
		}
		while( 0 != fileSet.getFileCount() )
			fileSet.remove( fileSet.getFileBlock( 0 ) );
		fileSet.isFinished = true;
		IO.closeQuietly( out );
		log.fine( file.getName() + " CRC = " + Long.toHexString( Checksums.crc32( file ) ) );
	}
	//
	// public static void mergeFiles2( FilePartSet fileset ) throws IOException
	// {
	// // FIXME this method is broken, DO NOT USE IT!
	// if( 1 == fileset.getFileCount() )
	// {
	// // all parts have finished,we just rename the first part's file name
	// File file = new File( fileset.getDirectory(), fileset.getBasename() + "."
	// + fileset.getExtname() );
	// fileset.getFile( 0 ).renameTo( file );
	// return;
	// }
	// /*
	// * �ϲ��ļ��Ĳ������£��ҵ�����ǰ�˿�ʼ�ģ�����ģ�����ɵģ���󳤶ȵ��ļ���
	// Ȼ�����Щ�ļ��ϲ�����һ��part
	// * file�����Ҹ�������ļ���properties
	// */
	// log.fine( fileset.toString() );
	// int finishedCount = 0;
	// for( int i = 0; i < fileset.getFileCount(); i++ )
	// if( false == FileUtilities.isPartFileFinished( fileset.getFile( i ) ) )
	// break;
	// else
	// finishedCount = i;
	// if( finishedCount < 1 )
	// return;
	// // now we knows that all the parts before [end] have finished
	// // we merge them to the first part
	// File dest = fileset.getFile( 0 );
	// long totalLength = getFileProperty( dest, PartUtilities.TOTAL_LENGTH );
	// log.fine( "merage " + finishedCount + " files to: " + dest.getName() );
	// BufferedOutputStream out = new BufferedOutputStream( new
	// FileOutputStream( dest, true ),
	// 512 * 1024 );
	// BufferedInputStream in = null;
	// byte[] buf = new byte[512 * 1024];
	// int len = 0;
	// for( int i = 1; i <= finishedCount; i++ )
	// {
	// File file = fileset.getFile( i );
	// totalLength += getFileProperty( file, PartUtilities.TOTAL_LENGTH );
	// in = new BufferedInputStream( new FileInputStream( fileset.getFile( i ) )
	// );
	// while( (len = in.read( buf )) != -1 )
	// out.write( buf, 0, len );
	// fileset.removePart( file );
	// IO.closeQuietly( in );
	// deleteFile( file );
	// log.fine( file.getName() + " merged" );
	// }
	// setFileProperty( dest, PartUtilities.TOTAL_LENGTH, totalLength );
	// IO.closeQuietly( out );
	// }
	//
	// public static boolean isPartFileFinished( File file ) throws IOException
	// {
	// Properties props = FileUtilities.getProperties( file );
	// long length = Long.parseLong( props.getProperty(
	// PartUtilities.TOTAL_LENGTH ) );
	// long alen = file.length();
	// log.fine( file.getName() + " required size: " + length );
	// log.fine( file.getName() + " actual size  : " + alen );
	// return alen == length;
	// }
	//
	// public static void setFileProperty( File file, String property, long
	// value ) throws IOException
	// {
	// Properties props = getProperties( file );
	// props.setProperty( property, Long.toString( value ) );
	// writePropertiesFile( getPropertiesFile( file ), props );
	// }
	//
	// public static long getFileProperty( File file, String property ) throws
	// IOException
	// {
	// Properties props = getProperties( file );
	// String v = props.getProperty( property );
	// return Long.parseLong( v );
	// }
	//
	// public static Properties getProperties( File file ) throws IOException
	// {
	// Properties props = new Properties();
	// File propsFile = FileUtilities.getPropertiesFile( file );
	// FileReader fr = new FileReader( propsFile );
	// props.load( fr );
	// IO.closeQuietly( fr );
	// return props;
	// }
	//
	// public static File getPropertiesFile( File file ) throws IOException
	// {
	// String basename = FileNameUtilities.getBaseName( file.getName() );
	// File props = new File( file.getParent(), basename +
	// PartUtilities.PROPERTIES );
	// if( false == props.exists() || false == props.isFile() )
	// props.createNewFile();
	// return props;
	// }
	//
	// public static void writePropertiesFile( File file, Properties props )
	// throws IOException
	// {
	// FileWriter fw = new FileWriter( file );
	// props.store( fw, "DO NOT EDIT THIS FILE" );
	// IO.closeQuietly( fw );
	// }
	//
	// public static void deleteFile( File file ) throws IOException
	// {
	// File props = getPropertiesFile( file );
	// props.delete();
	// file.delete();
	// }
}
